#/bin/bash

DIR="loops_cycle"
PATHS="paths"

#$1 - source file
#$2 - LLVM asm .ll file
#$3 - MODE - loop (printout bbs in cycle, DEFAULT) or tree (printout all bbs in entire tree)
mode=$3

function getbbexits {
# $1 - INPUT filename containing basicblock contents
# $2 - OUTPUT branches filename
# $3 - OUTPUT functioncalls filename
# $4 - currentblockidentifier

# outputs branches and functioncalls to stdout
# outputs branches to file branches
# outputs functioncalls to file functoncalls
   cat $1 | grep "br .*label " | tr "," "\n" | grep -o "label %[a-z0-9\#_]*" | cut -d "%" -f 2 | sort | uniq | sed -e "s/$/,$4/g" > $2
   echo branches: >&2
   cat $2 >&2
   cat $1 | grep " nounwind" | grep -o "@[^(]*(" | sort | uniq | sed -e "s/$/,$4/g" > $3
   echo functions: >&2
   cat $3 >&2

   children=$(cat $2 $3)
   echo STATE
   echo $4 
   echo END STATE

    for block in $children; do

      echo childbranchblock $block >&2
      if [ "$(grep "$block$" seenblocks)" != "" ]; then
          echo seen $block >&2
      else
        out=$(echo $block | sed -e "s/@\([^(]*\)(/\1/")
        if [ "$mode" == "tree" ]; then
          echo $out    
        else
          if [ -n "$(echo $4 | grep "$block")"  ]; then
#             if [ "$block" == "$headid" ]; then
                echo cycle detected:
                echo $4
          #else
          #   # insert into path
          #   sed -e "s/^$4/$block $4/" paths >
          fi
        fi
          echo $block >> seenblocks
      fi
      lastblock=$block
    done
}

srcfile=$(echo $1 | tr "/" "_" | tr " " "_" )

mkdir $DIR 2>/dev/null

# identify lines in src file containing loops
grep -n "." $1 | grep "while[ ]*([^)]*)\|for[ ]*([^)]*)" > $DIR/$srcfile.loops

if [ false ]; then

cat $2 | sed -e "s/^\(define\|declare\) /\?\1 /g" | tr "\n" "\!" | tr "\?" "\n" > functionsfile
# tag functionnames to bb blocks
rm -f functionsfile2
while read line; do

   if [ -n "$(echo $line | grep "^define \|declare ")" ]; then
      label=$(echo $line | grep -m 1 -o "@[^(^ ]*(" | head -n 1 | sed -e "s/@\([^(]*\)(/\1/g" )
   fi
   echo $line | sed -e "s/\!\([a-z0-9]*:\)/\!$label\#\1/g" -e "s/label %\([a-z0-9]*\)/label %$label\#\1/g" >> functionsfile2
done < functionsfile

cat functionsfile2 | tr "\!" "\n" | sed -e "s/^\([a-z0-9_\#]*:\)/\?\1/g" | tr "\n" "\!" | sed -e "s/\?\([a-z0-9_\#]*:\)/\n\1/g" > assemfile

fi

# for each loop
while read line; do

   # identify the first basic block within that loop
   echo $line
   srcline=$(echo $line | cut -d ":" -f 1)
   #echo $srcline
   grep -m 1 "llvm.dbg.stoppoint(i32 $srcline," assemfile | tr "\!" "\n" > loopbb
   if [ ! -s loopbb ]; then
      srcline=$(echo $srcline + 1 | bc )
      grep -m 1 "llvm.dbg.stoppoint(i32 $srcline," assemfile | tr "\!" "\n" > loopbb
   fi
   cat loopbb >&2

   #get headid basicblock identifier
   headid=$(cat loopbb | grep -o "^[^:]*:" | sed -e "s/://" )
   echo headid: $headid >&2
   if [ "$mode" == "tree" ]; then
     echo $headid
   else
     echo $headid > paths
   fi

   #first entry in seenblocks
   echo $headid > seenblocks
    
   # identify branch blocks and calls
   getbbexits loopbb branches functioncalls $headid
   
   #iterate thru each child basic block
   while read line_childb; do
#    echo line_childb: $line_childb
    childb=$(echo $line_childb | awk -F ',' '{ print $1 }')
    #state=$(echo $line_childb | cut -d " " -f 2- )
    
    # distinguish between function calls and basic blocks - retrieve from assemfile or functionsfile accordingly
    if [ "$(echo $childb | grep "^@")" == "" ]; then
      # basic block
      grep -m 1 "^$childb:" assemfile | tr "\!" "\n" > childblock
    else
      # functioncall
      grep -m 1 "^[^@]* $childb" functionsfile2 | tr "\!" "\n" > childblock
      echo functioncall: >&2
      cat childblock >&2
         if [ -n "$(head -n 1 childblock | grep "^declare " )" ]; then
             echo EXTERNAL:$childb | sed -e "s/@\([^(]*\)(/\1/"
             continue
         fi
    fi

      
      cat childblock >&2
      getbbexits childblock childbranches childfunctioncalls $line_childb
      cat childbranches >> branches

      cat childfunctioncalls >> functioncalls
   done < branches
   #iterate thru each child function

#   break
done < $DIR/$srcfile.loops
#done < extract

#tag each bacic block with all called child branches
#and functioncalls
#identify cyclic basic block paths - don't need

